package cn.zhuoqianmingyue.filter;

import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.util.StringUtils;

import cn.hutool.json.JSONUtil;
import cn.zhuoqianmingyue.cache.TicketCache;
import cn.zhuoqianmingyue.pojo.User;
import cn.zhuoqianmingyue.ticket.GrantingTicket;
import cn.zhuoqianmingyue.ticket.ServiceTicket;

public class SSOServerFilter implements Filter{
	private final String LOGINURL = "http://localhost:8080/ssoServer/login/login";
	private final String cookieName = "zhuoqianmingyue";
	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
			FilterChain filterChain) throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest )servletRequest;
		HttpServletResponse response = (HttpServletResponse )servletResponse;
		
		String uri = request.getRequestURI();
		
		if(uri.endsWith("sso/validateTicket")){
			String ticket = request.getParameter("ticket");
			String service = request.getParameter("service");
			
			String gtId = TicketCache.getGTByST(ticket);
			GrantingTicket grantingTicket = TicketCache.getGrantingTicket(gtId);
			User user = grantingTicket.getUser();
			String jsonStr = JSONUtil.toJsonStr(user);
			
			//让ticket过期
			ServiceTicket serviceTicket = grantingTicket.getServiceTicketMap().get(ticket);
			boolean expired = serviceTicket.isExpired();
			if(expired){
				serviceTicket.setExpired(false);
				response.getOutputStream().write(jsonStr.getBytes("UTF-8"));
				return;
			}else{
				response.sendRedirect(LOGINURL+"?srevice="+service+"&ERRORMSG=ticket已经过期！");
				return;
			}
			
			
		}else if(uri.endsWith("sso/signin")){
			String loginName = request.getParameter("loginName");
			String password = request.getParameter("password");
			String service = request.getParameter("service");
			if("lijunkui".equals(loginName)){
				UUID randomUUID = UUID.randomUUID();
				String ticketId = randomUUID.toString();
				GrantingTicket gt = new GrantingTicket();
				gt.setId(ticketId);
				User user = new User();
				user.setUserId(1l);
				user.setLoginName("lijunkui");
				user.setPassword("123456");
				gt.setUser(user);
				
				Cookie cookie = new Cookie("zhuoqianmingyue", ticketId);		
				cookie.setMaxAge(-1);	
				cookie.setPath("/");
				response.addCookie(cookie);
				TicketCache.putGrantingTicket(ticketId, gt);
				
				ServiceTicket st = new ServiceTicket();
				String stId = UUID.randomUUID().toString();
				st.setId(stId);
				st.setHost(service);
				ConcurrentHashMap<String, ServiceTicket> serviceTicketMap = gt.getServiceTicketMap();
				serviceTicketMap.put(stId, st);
				TicketCache.putSTAndGT(stId, ticketId);
				response.sendRedirect(service+"?ticket="+st.getId());
				return;
			}else{
				response.sendRedirect(LOGINURL+"?srevice="+service+"&ERRORMSG=登录名或者密码错误");
				return;
			}
		}else if(uri.endsWith("sso/authentication")){
			String gtId = getSSOCookie(request,response);
			String service =  request.getParameter("service");
			GrantingTicket gt = null;
			if(gtId != null){
				gt = TicketCache.getGrantingTicket(gtId);
			}
		
			if(StringUtils.isEmpty(service) || null == gtId || null == gt){
				response.sendRedirect(LOGINURL+"?srevice="+service);
				return;
			}
			
			ServiceTicket st = new ServiceTicket();
			String stId = UUID.randomUUID().toString();
			st.setId(stId);
			st.setHost(service);
			ConcurrentHashMap<String, ServiceTicket> serviceTicketMap = gt.getServiceTicketMap();
			serviceTicketMap.put(stId, st);
			TicketCache.putSTAndGT(stId, gt.getId());
			response.sendRedirect(service+"?ticket="+st.getId());
			return;
		}else if(uri.endsWith("sso/signout")){
			String gtCookie = getSSOCookie(request, response);
			String service = request.getParameter("service");
			ssoLogout(request,response,gtCookie);
			response.sendRedirect(LOGINURL+"?service="+service);
			return;
		}
		
		filterChain.doFilter(servletRequest, servletResponse);	
	}
	
	/**
	 * 单点退出
	 * @param request
	 * @param response
	 * @param chain
	 * @throws IOException
	 * @throws ServletException
	 */
	public void ssoLogout(HttpServletRequest request,HttpServletResponse response, String gtCookie) {
		// 清除cookie值
		removeSSOCookie(request,response, cookieName);
		GrantingTicket gt = TicketCache.getGrantingTicket(gtCookie);
		if (null != gt) {
			ConcurrentHashMap<String, ServiceTicket> serviceTicketMap = gt
					.getServiceTicketMap();

			Collection<ServiceTicket> stes = serviceTicketMap.values();
			ServiceTicket serviceTicket = null;
			//String host = null;
			for (Iterator<ServiceTicket> iterator = stes.iterator(); iterator
					.hasNext();) {
				serviceTicket = (ServiceTicket) iterator.next();
				noticeClientLogout(serviceTicket);
				TicketCache.removeServiceTicket(serviceTicket.getId());
			}
			
		}
		TicketCache.removeGrantingTicket(gtCookie);
	}
	/**
	 * 获得sso的cookie值
	 * @param response
	 * @param ticket
	 */
	public String getSSOCookie(HttpServletRequest request,HttpServletResponse response)
	{
		Cookie[] cookies = request.getCookies();
		String gtCookie = null;
		if(null != cookies)
		{
			Cookie cookie = null;
			for (int i = 0; i < cookies.length; i++) {
				cookie = cookies[i];
				if(cookieName.equals(cookie.getName()))
				{
					gtCookie = cookie.getValue();
					break;
				}
			}
		}
		return gtCookie;
	}
	public void removeSSOCookie(HttpServletRequest request,HttpServletResponse response, String name) {
		Cookie[] cookies = request.getCookies();
		if (null == cookies) {
			return;
		}

		for (Cookie cookie : cookies) {
			if (cookie.getName().equals(name)) {
				cookie.setValue(null);
				cookie.setMaxAge(0);// 立即销毁cookie
				cookie.setPath("/");
				response.addCookie(cookie);
				break;
			}
		}
	}
	
	/**
	 * 通知退出
	 * @param ticket
	 */
	public static void noticeClientLogout(ServiceTicket ticket){
			String logoutURL= ticket.getHost()+"?requestLogout="+ticket.getId();
			System.out.println("========logoutURL=="+logoutURL);
			clientLogout(logoutURL);
			return;
	}
	/**
	 * 通知客户端退出
	 * @param url
	 */
	public static void clientLogout(String url){
    	CloseableHttpClient  httpClient=HttpClients.createDefault();  
		HttpPost httppost = new HttpPost(url); 
		try {
			CloseableHttpResponse execute = httpClient.execute(httppost);
			execute.close();
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally{
			try {
				httpClient.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
    }
}
